home *** CD-ROM | disk | FTP | other *** search
- /* UDPTransport
-
- © Copyright 1991 Joachim Lindenberg, Karlsruhe. All rights reserved.
-
- This program illustrates how you can write your own transport systems.
-
- Created : Jan 18, 1991
- Revised : Jan 20, 1991 : added menu handling code, removed SIOW stuff.
- Jan 24, 1991 : added callback in notification. fixed abort sequences.
- added rudimentary DA support and about.
- Feb 5, 1991 : added alert warning about terminating UDP if there are
- other NetWork applications.
- Apr 28, 1991 : modifications for new TransportRecord, domain not yet implemented
- May 30, 1991 : modifications to use defined error codes.
- May 31, 1991 : modified to drop into debugger if aborting active message.
-
- This transport is limited in several ways:
- - it doesn´t support messages larger than 8KB (a limitation of .MacTCP)
- - it doesn´t support split information transfer, all data is packed into one UDP datagram
- - cannot abort UDP transfers in progress.
-
- Also, the user interface is akward at best.
- */
-
- #include <Stdio.h>
- #include <NetWork.h>
- #include <Devices.h>
- #include <SegLoad.h>
- #include <ToolUtils.h>
- #include <MacTCPCommonTypes.h>
- #include <UDPPB.h>
- #include <QuickDraw.h>
- #include <Events.h>
- #include <Menus.h>
- #include <Memory.h>
- #include <Windows.h>
- #include <Fonts.h>
- #include <Dialogs.h>
- #include <TextEdit.h>
- #include <Desk.h>
-
- #define UDPMaxSize 8000
- #define MemReserve 16384
-
- short UDPPort = 40;
- long HeaderSize = 40;
-
- #define HeaderOffset (sizeof (long))
-
- short MacTCPRefNum; StreamPtr UDPStream;
-
- typedef struct UDPMsgRec {
- MsgRec MsgRec;
- UDPiopb ParamBlock;
- wdsEntry WDS [5];
- } UDPMsgRec, *UDPMsgPtr;
-
- pascal void CallBack (MsgPtr Msg, void *Proc) = {0x205F, 0x4e90};
-
- void UDPCompletion (struct UDPiopb *iopb)
- {
- MsgPtr Msg;
- Msg = (MsgPtr) (((long) iopb) - sizeof (MsgRec));
- CallBack (Msg, (void*) Msg->MsgTrpPtr->TransportAttnRtn);
- }
-
- void UDPRcvAbort (UDPMsgPtr Msg)
- {
- if (Msg->ParamBlock.ioResult <= 0) {
- if (Msg->ParamBlock.csParam.receive.rcvBuffLen) {
- Msg->ParamBlock.csCode = UDPBfrReturn;
- Msg->ParamBlock.ioCompletion = NULL;
- PBControl ((ParmBlkPtr) &(Msg->ParamBlock), false);
- Msg->ParamBlock.csParam.receive.rcvBuffLen = 0;
- }
- Msg->MsgRec.MsgResult = eAbortMsg;
- }
- else {
- ProgramBreak ("\paborting active receive");
- while (Msg->ParamBlock.ioResult < 0) ; /* Sorry, active wait */
- }
- }
-
- void UDPListen (UDPMsgPtr Msg)
- {
- OSErr err;
- Msg->ParamBlock.csCode = UDPRead;
- Msg->ParamBlock.ioCRefNum = MacTCPRefNum;
- Msg->ParamBlock.udpStream = UDPStream;
- Msg->ParamBlock.csParam.receive.timeOut = 2;
- Msg->ParamBlock.csParam.receive.secondTimeStamp = 0;
- Msg->ParamBlock.ioCompletion = (UDPIOCompletionProc) UDPCompletion;
- Msg->ParamBlock.csParam.receive.userDataPtr = (Ptr) Msg;
- err = PBControl ((ParmBlkPtr) &(Msg->ParamBlock), true);
- }
-
- void UDPListenCompletion (UDPMsgPtr Msg)
- {
- if ((Msg->ParamBlock.csParam.receive.rcvBuffLen) && (* ((long*) Msg->ParamBlock.csParam.receive.rcvBuff) == HeaderSize)) {
- BlockMove ((void*) ( (long) Msg->ParamBlock.csParam.receive.rcvBuff + HeaderOffset),
- (void*) &(Msg->MsgRec.MsgSource), HeaderSize);
- Msg->MsgRec.MsgResult = Msg->ParamBlock.ioResult;
- if ((Msg->MsgRec.MsgResult == 0) && (Msg->MsgRec.MsgSource.a == Msg->MsgRec.MsgTrpPtr->TransportAddr))
- Msg->MsgRec.MsgResult = eLoopback;
- }
- else Msg->MsgRec.MsgResult = eVersion;
- }
-
- void UDPGet (UDPMsgPtr Msg)
- {
- BlockMove ((void*) ((long) Msg->ParamBlock.csParam.receive.rcvBuff + HeaderOffset +
- * (long*) Msg->ParamBlock.csParam.receive.rcvBuff),
- (void*) Msg->MsgRec.MsgPrioPtr, (Msg->MsgRec.MsgPrioSize));
- Msg->MsgRec.MsgResult = noErr;
- }
-
- void UDPAccept (UDPMsgPtr Msg)
- {
- BlockMove ((void*) ((long) Msg->ParamBlock.csParam.receive.rcvBuff + HeaderOffset + * (long*) Msg->ParamBlock.csParam.receive.rcvBuff
- + ((MsgPtr) ((long) Msg->ParamBlock.csParam.receive.rcvBuff + HeaderOffset))->MsgPrioSize),
- (void*) Msg->MsgRec.MsgCorePtr, (Msg->MsgRec.MsgCoreSize));
- Msg->MsgRec.MsgResult = noErr;
- }
-
- void UDPPostCompletion (UDPMsgPtr Msg)
- {
- Msg->MsgRec.MsgResult = Msg->ParamBlock.ioResult;
- }
-
- void UDPPost (UDPMsgPtr Msg)
- {
- int wdscount = 0;
- if (HeaderSize + Msg->MsgRec.MsgPrioSize + Msg->MsgRec.MsgCoreSize + sizeof (HeaderSize) > UDPMaxSize)
- Msg->MsgRec.MsgResult = eSizeLimit;
- else {
- Msg->WDS [wdscount].length = sizeof (HeaderSize);
- Msg->WDS [wdscount].ptr = (Ptr) &HeaderSize;
- if (Msg->WDS [wdscount].length) ++wdscount;
- Msg->WDS [wdscount].length = HeaderSize;
- Msg->WDS [wdscount].ptr = (Ptr) & (Msg->MsgRec.MsgSource);
- if (Msg->WDS [wdscount].length) ++wdscount;
- Msg->WDS [wdscount].length = Msg->MsgRec.MsgPrioSize;
- Msg->WDS [wdscount].ptr = (Ptr) Msg->MsgRec.MsgPrioPtr;
- if (Msg->WDS [wdscount].length) ++wdscount;
- Msg->WDS [wdscount].length = Msg->MsgRec.MsgCoreSize;
- Msg->WDS [wdscount].ptr = (Ptr) Msg->MsgRec.MsgCorePtr;
- if (Msg->WDS [wdscount].length) ++wdscount;
- Msg->WDS [wdscount].length = 0;
-
- Msg->ParamBlock.csCode = UDPWrite;
- Msg->ParamBlock.ioCRefNum = MacTCPRefNum;
- Msg->ParamBlock.ioCompletion = (UDPIOCompletionProc) UDPCompletion;
- Msg->ParamBlock.udpStream = UDPStream;
- Msg->ParamBlock.csParam.send.remoteHost = Msg->MsgRec.MsgDest.a; /* should be MsgDest */
- Msg->ParamBlock.csParam.send.remotePort = UDPPort;
- Msg->ParamBlock.csParam.send.wdsPtr = (Ptr) & Msg->WDS;
- Msg->ParamBlock.csParam.send.checkSum = 0;
- Msg->ParamBlock.csParam.send.sendLength = 0;
- Msg->ParamBlock.csParam.send.userDataPtr = (Ptr) Msg;
- PBControl ((ParmBlkPtr) &(Msg->ParamBlock), true);
- }
- }
-
- void UDPPostAbort (UDPMsgPtr Msg)
- {
- if (Msg->ParamBlock.ioResult <= 0) Msg->MsgRec.MsgResult = eAbortMsg;
- else {
- ProgramBreak ("\paborting active send");
- while (Msg->ParamBlock.ioResult < 0) ; /* Sorry, active wait */
- }
-
- }
-
- pascal void UDPTransport (short cmd, UDPMsgPtr Msg, TransportPtr Trp)
- {
- long savedA5 = SetA5 ((long) Trp->TransportVars);
- if (Msg) Msg->MsgRec.MsgCmd |= 1; /* next call expected is completion */
- switch (cmd) {
- case tListen : UDPListen (Msg); break;
- case tListen+tTickle : UDPListenCompletion (Msg); break;
-
- case tGet : UDPGet (Msg); break;
- case tAccept : UDPAccept (Msg); break;
-
- case tListen+tTimeout :
- case tListen+tTimeout1 :
- case tListen+tAbort :
- case tListen+tAbort1 :
-
- case tGet+tTimeout :
- case tGet+tTimeout1 :
- case tGet+tAbort :
- case tGet+tAbort1 :
-
- case tAccept+tTimeout :
- case tAccept+tTimeout1 :
- case tAccept+tAbort :
- case tAccept+tAbort1 : UDPRcvAbort (Msg); break;
-
- case tPost : UDPPost (Msg); break;
- case tPost+tTickle : UDPPostCompletion (Msg); break;
-
- case tPost+tTimeout :
- case tPost+tTimeout1 :
- case tPost+tAbort :
- case tPost+tAbort1 : UDPPostAbort (Msg); break;
-
- default : if (Msg) Msg->MsgRec.MsgResult = eCmdSequence; /* force error */
- }
- SetA5 (savedA5);
- }
-
- TransportRecord UDPDescription = {
- NULL, /* link to next transport in queue */
- UDPTransport, /* pointer to definition proc */
- NULL, /* name of transport */
- 'NetU', /* transport protocol (unique) signature */
- NULL, /* transport domain dependent string */
- 0, 1, -2, -1, /* local and other transport addresses */
- sizeof (UDPMsgRec), /* size of MsgRecord for this transport system */
- 0, 0, 0, /* various counters of listeners */
- 0, /* reserved for future use */
- NULL, /* private vars, may be longint, ptr, or handle */
- NULL, /* pointer to head of message queue */
- NULL /* pointer to attn routine (supplied by NetWork) */
- };
-
- void ErrorExit (char *s, short err)
- {
- if (err) {
- CheckError (s, err);
- ExitToShell ();
- }
- }
-
- pascal void UDPNotification (StreamPtr udpStream, unsigned short eventCode, TransportPtr Trp, struct ICMPReport *icmpMsg)
- {
- if (eventCode == UDPDataArrival) {
- ++Trp->TransportListensRequested;
- CallBack (NULL, (void*) Trp->TransportAttnRtn);
- }
- }
-
- OSErr UDPClosePort (void)
- {
- UDPiopb ParamBlock; OSErr err;
- ParamBlock.csCode = UDPRelease; ParamBlock.ioCRefNum = MacTCPRefNum;
- ParamBlock.udpStream = UDPStream;
- err = PBControl ((ParmBlkPtr) &ParamBlock, false);
- return (err);
- }
-
- OSErr UDPOpenPort (void)
- {
- UDPiopb ParamBlock; OSErr err;
- ParamBlock.csCode = 15; ParamBlock.ioCRefNum = MacTCPRefNum;
- err = PBControl ((ParmBlkPtr) &ParamBlock, false);
- UDPDescription.TransportAddr = (long) ParamBlock.udpStream;
- UDPDescription.TransportBCAddr = (long) ParamBlock.csParam.create.rcvBuff;
- UDPDescription.TransportBCAddr = (UDPDescription.TransportBCAddr & UDPDescription.TransportAddr)
- + ~UDPDescription.TransportBCAddr;
- ParamBlock.csCode = UDPCreate; ParamBlock.ioCRefNum = MacTCPRefNum;
- ParamBlock.csParam.create.rcvBuffLen = FreeMem () - MemReserve;
- ParamBlock.csParam.create.rcvBuff = NewPtr (ParamBlock.csParam.create.rcvBuffLen);
- if (ParamBlock.csParam.create.rcvBuff == NULL) ErrorExit ("\pNewPtr", MemError ());
- ParamBlock.csParam.create.notifyProc = (UDPNotifyProc) UDPNotification;
- ParamBlock.csParam.create.localPort = UDPPort;
- ParamBlock.csParam.create.userDataPtr = (Ptr) & UDPDescription;
- err = PBControl ((ParmBlkPtr) &ParamBlock, false);
- UDPStream = ParamBlock.udpStream;
- return (err);
- }
-
- /* removing a transport system may cause problems because it provides a service to
- other applications. It is safe to remove, if no other processes are executing,
- and if no messages are pending (Note that though no process is alive, there may
- still be messages pending).
-
- Testing for other processes doesn´t catch the possibility that the other processes
- might be transport systems as well.
- */
-
- Boolean NoMoreMessages (void)
- {
- MsgPtr p = *UDPDescription.TransportMsgQHead;
- while (p)
- if (p->MsgTrpPtr == &UDPDescription) return (false);
- else p = p->MsgLink;
- return (true);
- }
-
- Boolean SafeToExit (void)
- {
- int e = 0, n = 0; long signature;
- while (e == noErr) {
- e = GetIndProcess (&signature, ++n);
- if ((signature != 0) && (signature != UDPDescription.TransportID)) return (false);
- }
- return (NoMoreMessages ());
- }
-
- void InitToolBox (void)
- {
- MaxApplZone (); MoreMasters ();
- InitGraf(&qd.thePort); // {initialize QuickDraw}
- InitFonts (); // {initialize Font Manager}
- InitWindows (); // {initialize Window Manager}
- InitMenus (); // {initialize Menu Manager}
- TEInit (); // {initialize TextEdit}
- InitDialogs(NULL); // {initialize Dialog Manager}
- InitCursor (); // {call QuickDraw to make cursor (pointer) an arrow}
-
- SetMenuBar (GetNewMBar (256));
- AddResMenu (GetMHandle (256), 'DRVR');
- DrawMenuBar ();
- }
-
- void About (void)
- {
- Alert (256, NULL);
- }
-
- void OpenDA (int itemno)
- {
- Str255 daname;
- GetItem (GetMHandle (256), itemno, daname);
- OpenDeskAcc (daname);
- }
-
- Boolean Done = false, FrontMost = true;
-
- void DoMenu (long menuselection)
- {
- switch (HiWord (menuselection)) {
- case 256 : if (LoWord (menuselection) == 1) About ();
- else OpenDA (LoWord (menuselection));
- break;
- case 257 : if (SafeToExit () || (Alert (257, NULL) == 2)) {
- Done = true;
- ErrorExit ("\pRemoveTransport", RemoveTransport (&UDPDescription));
- break;
- }
- }
- HiliteMenu (0);
- }
-
- main ()
- {
- Str255 appname; short appref; Handle appparms;
- EventRecord Event; WindowPtr w;
-
- InitToolBox ();
-
- GetAppParms (appname, &appref, &appparms);
- UDPDescription.TransportName = NewString (appname);
- (long) UDPDescription.TransportVars = SetCurrentA5 ();
-
- ErrorExit ("\pInitNetWork", InitNetWork (nullEvent));
- ErrorExit ("\pMacTCP", OpenDriver ("\p.ipp", &MacTCPRefNum));
- ErrorExit ("\pUDPCreate", UDPOpenPort ());
-
- ErrorExit ("\pInstallTransport", InstallTransport (&UDPDescription));
-
- while (!Done || !NoMoreMessages ()) {
- if (WaitNextEvent (everyEvent, &Event, (Done || FrontMost) ? 60 : 0x7fffffff, NULL))
- switch (Event.what) {
- case mouseDown: if (FindWindow (Event.where, &w) == inMenuBar)
- DoMenu (MenuSelect (Event.where));
- break;
- case keyDown: if (Event.modifiers & cmdKey)
- DoMenu (MenuKey (Event.message & charCodeMask));
- break;
- case app4Evt : if (Event.message & 0xff000000 == 0x01000000)
- FrontMost = Event.message & 0x1;
- }
- }
- ErrorExit ("\pUDPRelease", UDPClosePort ());
- ErrorExit ("\pExitNetWork", ExitNetWork ());
- };
-